package com.lagou.sqlSession;

import com.lagou.enu.SqlType;
import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;

import java.lang.reflect.*;
import java.util.List;

public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }


    @Override
    public <E> List<E> selectList(String statementId, Object... param) throws Exception {

        simpleExecutor simpleExecutor = new simpleExecutor();
        MappedStatement mappedStatement = configuration.getStatementMap().get(statementId);
        List<Object> objectList = simpleExecutor.query(configuration, mappedStatement, param);
        return (List<E>) objectList;
    }

    @Override
    public <E> E selectOne(String statementId, Object... param) throws Exception {
        List<Object> objects = selectList(statementId, param);
        if (objects.size() == 1) {
            return (E) objects.get(0);
        } else if (objects.size() < 1) {
            return null;
        }
        throw new RuntimeException("tooMany");
    }

    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        Object o = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();
                String className = method.getDeclaringClass().getName();

                if (SqlType.SELECT_LIST.getMethod().equals(method.getName())) {
                    return selectList(className + "." + methodName, args);
                } else if (SqlType.SELECT_ID.getMethod().equals(method.getName())) {
                    return selectOne(className + "." + methodName, args);
                } else if (SqlType.UPDATE_TABLE.getMethod().equals(method.getName()) || SqlType.UPDATE_ID.getMethod().equals(method.getName())) {
                    return updateTable(className + "." + methodName, args);
                } else if (SqlType.DELETE_ID.getMethod().equals(method.getName()) || SqlType.DELETE_TABLE.getMethod().equals(method.getName())) {
                    return deleteTable(className + "." + methodName, args);
                }
                throw new RuntimeException("方法调用错误");
            }
        });
        return (T) o;
    }

    @Override
    public Integer updateTable(String statementId, Object... param) throws Exception {
        simpleExecutor simpleExecutor = new simpleExecutor();
        MappedStatement mappedStatement = configuration.getStatementMap().get(statementId);

        return simpleExecutor.update(configuration, mappedStatement, param);
    }

    @Override
    public Integer deleteTable(String statementId, Object... param) throws Exception {
        simpleExecutor simpleExecutor = new simpleExecutor();
        MappedStatement mappedStatement = configuration.getStatementMap().get(statementId);
        return simpleExecutor.delete(configuration, mappedStatement, param);
    }

    @Override
    public Integer updateTableById(String statementId, Object... param) throws Exception {

        return updateTable(statementId, param);
    }

    @Override
    public Integer deleteTableById(String statementId, Object... param) throws Exception {

        return deleteTable(statementId, param);
    }


}
